﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="GetAssemblyFileVersion.cs" company="devdigital">
//   devdigital
// </copyright>
// <summary>
//   GetAssemblyFileVersion.cs
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace BuildUp.MSBuildTasks
{
    using System;
    using System.IO;
    using System.Text.RegularExpressions;

    using Microsoft.Build.Framework;

    /// <summary>
    /// Adapted from http://stackoverflow.com/questions/1252002/read-assemblyfileversion-from-assemblyinfo-post-compile
    /// </summary>
    public class GetAssemblyFileVersion : ITask
    {
        /// <summary>
        /// Gets or sets the file path assembly info.
        /// </summary>
        /// <value>The file path assembly info.</value>
        [Required]
        public string FilePathAssemblyInfo { get; set; }

        /// <summary>
        /// Gets or sets the assembly file version.
        /// </summary>
        /// <value>The assembly file version.</value>
        [Output]
        public string AssemblyFileVersion { get; set; }

        /// <summary>
        /// Gets or sets the assembly file major version.
        /// </summary>
        /// <value>The assembly file major version.</value>
        [Output]
        public string AssemblyFileVersionMajor { get; set; }

        /// <summary>
        /// Gets or sets the assembly file minor version.
        /// </summary>
        /// <value>The assembly file minor version.</value>
        [Output]
        public string AssemblyFileVersionMinor { get; set; }

        /// <summary>
        /// Gets or sets the assembly file build version.
        /// </summary>
        /// <value>The assembly file build version.</value>
        [Output]
        public string AssemblyFileVersionBuild { get; set; }

        /// <summary>
        /// Gets or sets the assembly file revision version.
        /// </summary>
        /// <value>The assembly file revision version.</value>
        [Output]
        public string AssemblyFileVersionRevision { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="GetAssemblyFileVersion"/> is success.
        /// </summary>
        /// <value><c>true</c> if success; otherwise, <c>false</c>.</value>
        [Output]
        public bool Success { get; set; }

        /// <summary>
        /// Gets or sets the build engine associated with the task.
        /// </summary>
        /// <value></value>
        /// <returns>The build engine associated with the task.</returns>
        public IBuildEngine BuildEngine { get; set; }

        /// <summary>
        /// Gets or sets any host object that is associated with the task.
        /// </summary>
        /// <value></value>
        /// <returns>The host object associated with the task.</returns>
        public ITaskHost HostObject { get; set; }

        /// <summary>
        /// Executes a task.
        /// </summary>
        /// <returns>
        /// true if the task executed successfully; otherwise, false.
        /// </returns>
        public bool Execute()
        {
            StreamReader streamreaderAssemblyInfo = null;
            Match matchVersion;
            Group groupVersion;
            this.AssemblyFileVersion = String.Empty;

            try
            {
                this.Success = true;
                streamreaderAssemblyInfo = new StreamReader(this.FilePathAssemblyInfo);

                string strLine;
                while ((strLine = streamreaderAssemblyInfo.ReadLine()) != null)
                {
                    matchVersion = Regex.Match(strLine, @"(?:AssemblyFileVersion\("")(?<ver>(\d*)\.(\d*)(\.(\d*)(\.(\d*))?)?)(?:""\))", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.ExplicitCapture);

                    if (!matchVersion.Success)
                    {
                        continue;
                    }

                    groupVersion = matchVersion.Groups["ver"];

                    if (!groupVersion.Success || String.IsNullOrEmpty(groupVersion.Value))
                    {
                        continue;
                    }

                    this.AssemblyFileVersion = groupVersion.Value;

                    var values = this.AssemblyFileVersion.Split('.');
                    if (values.Length == 4)
                    {
                        this.AssemblyFileVersionMajor = values[0];
                        this.AssemblyFileVersionMinor = values[1];
                        this.AssemblyFileVersionBuild = values[2];
                        this.AssemblyFileVersionRevision = values[3];
                    }

                    break;
                }
            }
            catch (Exception e)
            {
                var args = new BuildMessageEventArgs(e.Message, string.Empty, "GetAssemblyFileVersion", MessageImportance.High);
                this.BuildEngine.LogMessageEvent(args);
                this.Success = false;
            }
            finally
            {
                if (streamreaderAssemblyInfo != null)
                {
                    streamreaderAssemblyInfo.Close();
                }
            }

            return this.Success;
        }
    }
}